<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <!-- hexo-inject:begin --><!-- hexo-inject:end --><meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#49b1f5">
<meta name="generator" content="Hexo 5.3.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/favicon-180x180-yaowan.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-yaowan.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-yaowan.png">
  <link rel="mask-icon" href="/images/logo-yaowan.svg" color="#49b1f5">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css">
  <link rel="stylesheet" href="//cdn.jsdelivr.net/gh/fancyapps/fancybox@3/dist/jquery.fancybox.min.css">
  <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/pace-js@1/themes/blue/pace-theme-minimal.css">
  <script src="//cdn.jsdelivr.net/npm/pace-js@1/pace.min.js"></script>

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"zhouyuqian.com","root":"/","scheme":"Mist","version":"7.7.2","exturl":false,"sidebar":{"position":"right","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":"default","style":"flat"},"back2top":{"enable":true,"sidebar":false,"scrollpercent":true},"bookmark":{"enable":true,"color":"#49b1f5","save":"auto"},"fancybox":true,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":"valine","storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":"ture"},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="Chisel 3">
<meta property="og:type" content="article">
<meta property="og:title" content="chisel 学习（1）">
<meta property="og:url" content="https://zhouyuqian.com/2021/05/24/chisel-start/index.html">
<meta property="og:site_name" content="Fitz&#39;s Blog - 快乐学习每一天">
<meta property="og:description" content="Chisel 3">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://pic.zhouyuqian.com/img/20210726235317.svg">
<meta property="og:image" content="https://pic.zhouyuqian.com/img/20210727174715.png">
<meta property="og:image" content="https://pic.zhouyuqian.com/img/20210727174733.png">
<meta property="article:published_time" content="2021-05-24T11:29:18.000Z">
<meta property="article:modified_time" content="2022-03-29T03:28:33.000Z">
<meta property="article:author" content="Fitz">
<meta property="article:tag" content="FPGA">
<meta property="article:tag" content="chisel">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://pic.zhouyuqian.com/img/20210726235317.svg">

<link rel="canonical" href="https://zhouyuqian.com/2021/05/24/chisel-start/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true
  };
</script>

  <title>chisel 学习（1） | Fitz's Blog - 快乐学习每一天</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript><!-- hexo-inject:begin --><!-- hexo-inject:end -->

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <!-- hexo-inject:begin --><!-- hexo-inject:end --><div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <div>
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">Fitz's Blog - 快乐学习每一天</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>


<nav class="site-nav">
  
  <ul id="menu" class="menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-fw fa-home"></i>首页</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="fa fa-fw fa-user"></i>关于</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-fw fa-tags"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-fw fa-th"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i>归档</a>

  </li>
        <li class="menu-item menu-item-ariang">

    <a href="/AriaNg/" rel="section"><i class="fa fa-fw fa-cloud-download"></i>AriaNg</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>

</nav>
  <div class="site-search">
    <div class="popup search-popup">
    <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocorrect="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result"></div>

</div>
<div class="search-pop-overlay"></div>

  </div>
</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>
  <a role="button" class="book-mark-link book-mark-link-fixed"></a>

  <a href="https://github.com/Starrynightzyq" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content">
            

  <div class="posts-expand">
      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block " lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://zhouyuqian.com/2021/05/24/chisel-start/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.jpg">
      <meta itemprop="name" content="Fitz">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Fitz's Blog - 快乐学习每一天">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          chisel 学习（1）
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-05-24 19:29:18" itemprop="dateCreated datePublished" datetime="2021-05-24T19:29:18+08:00">2021-05-24</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2022-03-29 11:28:33" itemprop="dateModified" datetime="2022-03-29T11:28:33+08:00">2022-03-29</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/chisel/" itemprop="url" rel="index"><span itemprop="name">chisel</span></a>
                </span>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>9.7k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="fa fa-clock-o"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>9 分钟</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <figure>
<img src="https://pic.zhouyuqian.com/img/20210726235317.svg" alt="Chisel 3"><figcaption aria-hidden="true">Chisel 3</figcaption>
</figure>
<a id="more"></a>
<h1 id="什么是-chisel">什么是 chisel</h1>
<p>https://www.chisel-lang.org/</p>
<h1 id="学习资料">学习资料</h1>
<ol type="1">
<li><a target="_blank" rel="noopener" href="https://github.com/freechipsproject/chisel-bootcamp">Chisel Bootcamp</a>是一个很不错的chisel教程, 还支持在线运行chisel代码, 你可以一边编写chisel代码一边学习. 其中
<ul>
<li>第1章是scala入门</li>
<li>第2章是chisel基础</li>
<li>第3章是scala高级特性和chisel的混合使用</li>
<li>第4章是FIRRTL后端相关内容 你需要完成前两章的学习, 同时我们强烈建议你学习第3章. 第4章和本课程没有直接关系, 可以作为课外阅读材料.</li>
</ul></li>
<li><a target="_blank" rel="noopener" href="https://www.chiselchina.com/archives/">Chisel Bootcamp 中文</a> 这个是翻译成中文的 Chisel Bootcamp</li>
<li><a target="_blank" rel="noopener" href="https://www.chisel-lang.org/chisel3/docs/introduction.html">Chisel Users Guideopen in new window</a>比较系统地整理了chisel的特性, 也是不错的入门教程.</li>
<li><a target="_blank" rel="noopener" href="https://www.chisel-lang.org/api/latest/chisel3/index.html">Chisel API</a>详细地列出了chisel库的所有API供参考.</li>
<li><a target="_blank" rel="noopener" href="https://github.com/freechipsproject/chisel-cheatsheet/releases/latest/download/chisel_cheatsheet.pdf">Chisel小抄open in new window</a>简明地列出了chisel语言的大部分用法.</li>
<li><a target="_blank" rel="noopener" href="https://github.com/schoeberl/chisel-book">schoeberl/chisel-book</a></li>
<li><a target="_blank" rel="noopener" href="https://github.com/schoeberl/chisel-examples">schoeberl/chisel-examples</a></li>
</ol>
<h1 id="安装">安装</h1>
<p><a target="_blank" rel="noopener" href="https://www.scala-sbt.org/release/docs/Setup.html#Installing+sbt">Installing sbt</a></p>
<p>Follow the instructions from <a target="_blank" rel="noopener" href="https://github.com/freechipsproject/chisel3">Chisel3</a> and <a target="_blank" rel="noopener" href="https://github.com/freechipsproject/firrtl">firrtl</a> websites.</p>
<p>Docker:</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https:<span class="regexp">//gi</span>thub.com<span class="regexp">/muojp/</span>docker-sbt-chisel.git</span><br></pre></td></tr></table></figure>
<p>OR: 使用 <a target="_blank" rel="noopener" href="https://github.com/OpenXiangShan/chisel-playground.git">OpenXiangShan/chisel-playground</a> 项目，已经配置好了环境，使用 <a target="_blank" rel="noopener" href="https://com-lihaoyi.github.io/mill">mill</a> 作为 Scala 编译器.</p>
<h1 id="before-start">Before Start</h1>
<p>首先需要理解Scala：</p>
<h1 id="语法">语法</h1>
<h2 id="variables-and-constants---var-and-val">Variables and Constants - var and val</h2>
<p>推荐使用 val (常量)</p>
<h2 id="seq">Seq</h2>
<h2 id="when">when</h2>
<p><strong>等于</strong>要使用 <code>===</code></p>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">when ( myData === <span class="number">3.</span><span class="type">U</span> ) &#123;</span><br><span class="line">  <span class="comment">// Some logic to run when myData equals 3.</span></span><br><span class="line">&#125; .elsewhen ( myData === <span class="number">1.</span><span class="type">U</span> ) &#123;</span><br><span class="line">   <span class="comment">// Some logic to run when myData equals 1.</span></span><br><span class="line">&#125; .otherwise &#123;</span><br><span class="line">  <span class="comment">// Some logic to run when myData is neither 3 nor 1.</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">  <span class="comment">// Returns the current `when` condition</span></span><br><span class="line">when (a) &#123;</span><br><span class="line">  when (b) &#123;</span><br><span class="line">    when (c) &#123;</span><br><span class="line">    &#125;.otherwise &#123;</span><br><span class="line">      when.cond <span class="comment">// this is equal to: a &amp;&amp; b &amp;&amp; !c</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="for">for</h2>
<p>其功能相当于 Verilog 中的 generator</p>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(i &lt;- <span class="number">0</span> until consts.length) &#123;</span><br><span class="line">      muls += regs(i) * consts(i).<span class="type">U</span></span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure>
<h2 id="if-or-when">if or when ?</h2>
<p><code>if</code> 是 scala 的语法，不能综合；</p>
<p><code>when</code> 是 chisel 的语法，等同于 Verilog 中的 <code>if</code>；</p>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">RegisterFile</span>(<span class="params">readPorts: <span class="type">Int</span></span>) <span class="keyword">extends</span> <span class="title">Module</span> </span>&#123;</span><br><span class="line">    require(readPorts &gt;= <span class="number">0</span>)</span><br><span class="line">    <span class="keyword">val</span> io = <span class="type">IO</span>(<span class="keyword">new</span> <span class="type">Bundle</span> &#123;</span><br><span class="line">        <span class="keyword">val</span> wen   = <span class="type">Input</span>(<span class="type">Bool</span>())</span><br><span class="line">        <span class="keyword">val</span> waddr = <span class="type">Input</span>(<span class="type">UInt</span>(<span class="number">5.</span><span class="type">W</span>))</span><br><span class="line">        <span class="keyword">val</span> wdata = <span class="type">Input</span>(<span class="type">UInt</span>(<span class="number">32.</span><span class="type">W</span>))</span><br><span class="line">        <span class="keyword">val</span> raddr = <span class="type">Input</span>(<span class="type">Vec</span>(readPorts, <span class="type">UInt</span>(<span class="number">5.</span><span class="type">W</span>)))</span><br><span class="line">        <span class="keyword">val</span> rdata = <span class="type">Output</span>(<span class="type">Vec</span>(readPorts, <span class="type">UInt</span>(<span class="number">32.</span><span class="type">W</span>)))</span><br><span class="line">    &#125;)</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// A Register of a vector of UInts</span></span><br><span class="line">    <span class="keyword">val</span> reg = <span class="type">RegInit</span>(<span class="type">VecInit</span>(<span class="type">Seq</span>.fill(<span class="number">32</span>)(<span class="number">0.</span><span class="type">U</span>(<span class="number">32.</span><span class="type">W</span>))))</span><br><span class="line">    </span><br><span class="line">    when(io.wen) &#123;</span><br><span class="line">        reg(io.waddr) := io.wdata</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">for</span>(i &lt;- <span class="number">0</span> until readPorts) &#123;</span><br><span class="line">        when(io.raddr(i) === <span class="number">0.</span><span class="type">U</span>) &#123;</span><br><span class="line">            io.rdata(i) := <span class="number">0.</span><span class="type">U</span>(<span class="number">32.</span><span class="type">W</span>)</span><br><span class="line">        &#125;.otherwise &#123;</span><br><span class="line">            io.rdata(i) := reg(io.raddr(i))</span><br><span class="line">        &#125;</span><br><span class="line"><span class="comment">//         if(io.raddr(i) == 0.U) io.rdata(i) := 0.U(32.W)</span></span><br><span class="line"><span class="comment">//         else io.rdata(i) := reg(io.raddr(i))</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="加法">加法</h2>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// a +&amp; b 包含进位, 而 a + b 不包含</span></span><br><span class="line">io.sum := io.in0 +&amp; io.in1</span><br></pre></td></tr></table></figure>
<h2 id="获得-verilog-代码">获得 Verilog 代码</h2>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">println(getVerilog(<span class="keyword">new</span> &lt;module&gt;))</span><br></pre></td></tr></table></figure>
<h2 id="可视化">可视化</h2>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">visualize(() =&gt; <span class="keyword">new</span> &lt;module&gt;)</span><br></pre></td></tr></table></figure>
<h2 id="带有decoupled接口的模块">带有<code>Decoupled</code>接口的模块</h2>
<p><code>Decoupled</code>可以将基本的chisel数据类型包装起来，并为其提供<code>ready</code>和<code>valid</code>信号。 Testers2提供了一些很好的工具，可以自动并可靠地测试这些接口。</p>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">case</span> <span class="class"><span class="keyword">class</span> <span class="title">QueueModule</span>[<span class="type">T</span> &lt;: <span class="type">Data</span>](<span class="params">ioType: <span class="type">T</span>, entries: <span class="type">Int</span></span>) <span class="keyword">extends</span> <span class="title">MultiIOModule</span> </span>&#123;</span><br><span class="line">  <span class="keyword">val</span> in = <span class="type">IO</span>(<span class="type">Flipped</span>(<span class="type">Decoupled</span>(ioType)))</span><br><span class="line">  <span class="keyword">val</span> out = <span class="type">IO</span>(<span class="type">Decoupled</span>(ioType))</span><br><span class="line">  out &lt;&gt; <span class="type">Queue</span>(in, entries)</span><br><span class="line">&#125;</span><br><span class="line">visualize(() =&gt; <span class="keyword">new</span> <span class="type">QueueModule</span>(<span class="type">UInt</span>(<span class="number">9.</span><span class="type">W</span>), entries = <span class="number">200</span>))</span><br><span class="line">println(getVerilog(<span class="keyword">new</span> <span class="type">QueueModule</span>(<span class="type">UInt</span>(<span class="number">9.</span><span class="type">W</span>), entries = <span class="number">200</span>)))</span><br></pre></td></tr></table></figure>
<figure>
<img src="https://pic.zhouyuqian.com/img/20210727174715.png" alt="q"><figcaption aria-hidden="true">q</figcaption>
</figure>
<p><strong>计算最大公约数：</strong></p>
<p><strong>src</strong></p>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 输入接口</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">GcdInputBundle</span>(<span class="params">val w: <span class="type">Int</span></span>) <span class="keyword">extends</span> <span class="title">Bundle</span> </span>&#123;</span><br><span class="line">  <span class="keyword">val</span> value1 = <span class="type">UInt</span>(w.<span class="type">W</span>)</span><br><span class="line">  <span class="keyword">val</span> value2 = <span class="type">UInt</span>(w.<span class="type">W</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 输出接口</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">GcdOutputBundle</span>(<span class="params">val w: <span class="type">Int</span></span>) <span class="keyword">extends</span> <span class="title">Bundle</span> </span>&#123;</span><br><span class="line">  <span class="keyword">val</span> value1 = <span class="type">UInt</span>(w.<span class="type">W</span>)</span><br><span class="line">  <span class="keyword">val</span> value2 = <span class="type">UInt</span>(w.<span class="type">W</span>)</span><br><span class="line">  <span class="keyword">val</span> gcd    = <span class="type">UInt</span>(w.<span class="type">W</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// GCD</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * 使用减法来计算GCD。</span></span><br><span class="line"><span class="comment">  * 从寄存器 x 和 y 中较大一个中减去较小的一个，直到寄存器 y 为零。</span></span><br><span class="line"><span class="comment">  * 输入寄存器 x 的值就是最大公约数</span></span><br><span class="line"><span class="comment">  * 返回包含两个输入值及其GCD的包</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">DecoupledGcd</span>(<span class="params">width: <span class="type">Int</span></span>) <span class="keyword">extends</span> <span class="title">MultiIOModule</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">val</span> input = <span class="type">IO</span>(<span class="type">Flipped</span>(<span class="type">Decoupled</span>(<span class="keyword">new</span> <span class="type">GcdInputBundle</span>(width))))</span><br><span class="line">  <span class="keyword">val</span> output = <span class="type">IO</span>(<span class="type">Decoupled</span>(<span class="keyword">new</span> <span class="type">GcdOutputBundle</span>(width)))</span><br><span class="line"></span><br><span class="line">  <span class="keyword">val</span> xInitial    = <span class="type">Reg</span>(<span class="type">UInt</span>())</span><br><span class="line">  <span class="keyword">val</span> yInitial    = <span class="type">Reg</span>(<span class="type">UInt</span>())</span><br><span class="line">  <span class="keyword">val</span> x           = <span class="type">Reg</span>(<span class="type">UInt</span>())</span><br><span class="line">  <span class="keyword">val</span> y           = <span class="type">Reg</span>(<span class="type">UInt</span>())</span><br><span class="line">  <span class="keyword">val</span> busy        = <span class="type">RegInit</span>(<span class="literal">false</span>.<span class="type">B</span>)</span><br><span class="line">  <span class="keyword">val</span> resultValid = <span class="type">RegInit</span>(<span class="literal">false</span>.<span class="type">B</span>)</span><br><span class="line"></span><br><span class="line">  input.ready := ! busy</span><br><span class="line">  output.valid := resultValid</span><br><span class="line">  output.bits := <span class="type">DontCare</span></span><br><span class="line"></span><br><span class="line">  when(busy)  &#123;</span><br><span class="line">    <span class="comment">// 在计算期间，从每次较大的值中减去较小的值</span></span><br><span class="line">    when(x &gt; y) &#123;</span><br><span class="line">      x := x - y</span><br><span class="line">    &#125;.otherwise &#123;</span><br><span class="line">      y := y - x</span><br><span class="line">    &#125;</span><br><span class="line">    when(y === <span class="number">0.</span><span class="type">U</span>) &#123;</span><br><span class="line">      <span class="comment">// 当 y 变为零时，计算结束，将输出置为 valid</span></span><br><span class="line">      output.bits.gcd := x</span><br><span class="line">      output.bits.value1 := xInitial</span><br><span class="line">      output.bits.value2 := yInitial</span><br><span class="line">      output.bits.gcd := x</span><br><span class="line">      output.valid := <span class="literal">true</span>.<span class="type">B</span></span><br><span class="line">      busy := <span class="literal">false</span>.<span class="type">B</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;.otherwise &#123;</span><br><span class="line">    when(input.valid) &#123;</span><br><span class="line">      <span class="comment">// 当有可用的有效数据且没有进行计算时，获取新值并开始计算</span></span><br><span class="line">      <span class="keyword">val</span> bundle = input.deq()</span><br><span class="line">      x := bundle.value1</span><br><span class="line">      y := bundle.value2</span><br><span class="line">      xInitial := bundle.value1</span><br><span class="line">      yInitial := bundle.value2</span><br><span class="line">      busy := <span class="literal">true</span>.<span class="type">B</span></span><br><span class="line">      resultValid := <span class="literal">false</span>.<span class="type">B</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>tb</strong></p>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">test(<span class="keyword">new</span> <span class="type">DecoupledGcd</span>(<span class="number">16</span>)) &#123; dut =&gt;</span><br><span class="line">  dut.input.initSource().setSourceClock(dut.clock)</span><br><span class="line">  dut.output.initSink().setSinkClock(dut.clock)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">val</span> testValues = <span class="keyword">for</span> &#123; x &lt;- <span class="number">1</span> to <span class="number">10</span>; y &lt;- <span class="number">1</span> to <span class="number">10</span>&#125; <span class="keyword">yield</span> (x, y)</span><br><span class="line">  <span class="keyword">val</span> inputSeq = testValues.map &#123; <span class="keyword">case</span> (x, y) =&gt;</span><br><span class="line">    (<span class="keyword">new</span> <span class="type">GcdInputBundle</span>(<span class="number">16</span>)).<span class="type">Lit</span>(_.value1 -&gt; x.<span class="type">U</span>, _.value2 -&gt; y.<span class="type">U</span>)</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">val</span> resultSeq = testValues.map &#123; <span class="keyword">case</span> (x, y) =&gt;</span><br><span class="line">    <span class="keyword">new</span> <span class="type">GcdOutputBundle</span>(<span class="number">16</span>).<span class="type">Lit</span>(_.value1 -&gt; x.<span class="type">U</span>, _.value2 -&gt; y.<span class="type">U</span>, _.gcd -&gt; <span class="type">BigInt</span>(x).gcd(<span class="type">BigInt</span>(y)).<span class="type">U</span>)</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// fork join 并行测试</span></span><br><span class="line">  fork &#123;</span><br><span class="line">    dut.input.enqueueSeq(inputSeq)</span><br><span class="line">  &#125;.fork &#123;</span><br><span class="line">    dut.output.expectDequeueSeq(resultSeq)</span><br><span class="line">  &#125;.join()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="queues">Queues</h2>
<p><code>Queue</code> creates a FIFO (first-in, first-out) queue with Decoupled interfaces on both sides, allowing backpressure. Both the data type and number of elements are configurable.</p>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyQueue</span>(<span class="params">width: <span class="type">Int</span>, len: <span class="type">Int</span></span>) <span class="keyword">extends</span> <span class="title">Module</span> </span>&#123;</span><br><span class="line">    <span class="keyword">val</span> io = <span class="type">IO</span>(<span class="keyword">new</span> <span class="type">Bundle</span> &#123;</span><br><span class="line">        <span class="keyword">val</span> in = <span class="type">Flipped</span>(<span class="type">Decoupled</span>(<span class="type">UInt</span>(width.<span class="type">W</span>)))</span><br><span class="line">        <span class="keyword">val</span> out = <span class="type">Decoupled</span>(<span class="type">UInt</span>(width.<span class="type">W</span>))</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="keyword">val</span> fifo = <span class="type">Queue</span>(io.in, len)</span><br><span class="line">    io.out &lt;&gt; fifo</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">visualize(() =&gt; <span class="keyword">new</span> <span class="type">MyQueue</span>(<span class="number">32</span>, <span class="number">10</span>))</span><br><span class="line">println(getVerilog(<span class="keyword">new</span> <span class="type">MyQueue</span>(<span class="number">32</span>, <span class="number">10</span>)))</span><br></pre></td></tr></table></figure>
<figure>
<img src="https://pic.zhouyuqian.com/img/20210727174733.png" alt="Queues"><figcaption aria-hidden="true">Queues</figcaption>
</figure>
<h2 id="arbiters">Arbiters</h2>
<p>Arbiters routes data from <em>n</em> <code>DecoupledIO</code> sources to one <code>DecoupledIO</code> sink, given a prioritization. There are two types included in Chisel:</p>
<ul>
<li><code>Arbiter</code>: prioritizes lower-index producers</li>
<li><code>RRArbiter</code>: runs in round-robin order</li>
</ul>
<p>Note that Arbiter routing is implemented in <strong>combinational logic</strong>.</p>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyArbiter</span>(<span class="params"><span class="type">InNum</span>: <span class="type">Int</span>, width: <span class="type">Int</span></span>) <span class="keyword">extends</span> <span class="title">Module</span> </span>&#123;</span><br><span class="line">    <span class="comment">// Example circuit using a priority arbiter</span></span><br><span class="line">    <span class="keyword">val</span> io = <span class="type">IO</span>(<span class="keyword">new</span> <span class="type">Bundle</span> &#123;</span><br><span class="line">      <span class="keyword">val</span> in = <span class="type">Flipped</span>(<span class="type">Vec</span>(<span class="type">InNum</span>, <span class="type">Decoupled</span>(<span class="type">UInt</span>(width.<span class="type">W</span>))))</span><br><span class="line">      <span class="keyword">val</span> out = <span class="type">Decoupled</span>(<span class="type">UInt</span>(width.<span class="type">W</span>))</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="comment">// Arbiter doesn&#x27;t have a convenience constructor, so it&#x27;s built like any Module</span></span><br><span class="line">    <span class="keyword">val</span> arbiter = <span class="type">Module</span>(<span class="keyword">new</span> <span class="type">Arbiter</span>(<span class="type">UInt</span>(width.<span class="type">W</span>), <span class="type">InNum</span>))  <span class="comment">// 2 to 1 Priority Arbiter</span></span><br><span class="line">    arbiter.io.in &lt;&gt; io.in</span><br><span class="line">    io.out &lt;&gt; arbiter.io.out</span><br><span class="line">&#125;</span><br><span class="line">println(getVerilog(<span class="keyword">new</span> <span class="type">MyArbiter</span>(<span class="number">2</span>, <span class="number">32</span>)))</span><br></pre></td></tr></table></figure>
<h2 id="popcount">PopCount</h2>
<p>PopCount returns the number of high (1) bits in the input as a <code>UInt</code>.</p>
<p>计算 <code>1</code> 的个数。</p>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">io.out := <span class="type">PopCount</span>(io.in)</span><br></pre></td></tr></table></figure>
<h2 id="reverse">Reverse</h2>
<p>Reverse returns the bit-reversed input.</p>
<p>翻转。</p>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">io.out := <span class="type">Reverse</span>(io.in)</span><br></pre></td></tr></table></figure>
<h2 id="onehot-encoding-utilities">OneHot encoding utilities</h2>
<p>OneHot is an encoding of integers where there is one wire for each value, and exactly one wire is high. This allows the efficient creation of some functions, for example muxes. However, behavior may be undefined if the one-wire-high condition is not held.</p>
<ul>
<li>UInt to OneHot: <code>UIntToOH</code></li>
<li>OneHot to UInt: <code>OHToUInt</code></li>
</ul>
<h2 id="muxes">Muxes</h2>
<p>These muxes take in a list of values with select signals, and output the value associated with the lowest-index select signal.</p>
<p>These can either take a list of (select: Bool, value: Data) tuples, or corresponding lists of selects and values as arguments. For simplicity, the examples below only demonstrate the second form.</p>
<h3 id="priority-mux">Priority Mux</h3>
<p>A <code>PriorityMux</code> outputs the value associated with the lowest-index asserted select signal.</p>
<h3 id="onehot-mux">OneHot Mux</h3>
<p>An <code>Mux1H</code> provides an efficient implementation when it is guaranteed that exactly one of the select signals will be high. Behavior is undefined if the assumption is not true.</p>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyPriorityMux</span>(<span class="params"><span class="type">InNum</span>: <span class="type">Int</span>, width: <span class="type">Int</span></span>) <span class="keyword">extends</span> <span class="title">Module</span> </span>&#123;</span><br><span class="line">    <span class="comment">// Example circuit using PriorityMux</span></span><br><span class="line">    <span class="keyword">val</span> io = <span class="type">IO</span>(<span class="keyword">new</span> <span class="type">Bundle</span> &#123;</span><br><span class="line">      <span class="keyword">val</span> in_sels = <span class="type">Input</span>(<span class="type">Vec</span>(<span class="type">InNum</span>, <span class="type">Bool</span>()))</span><br><span class="line">      <span class="keyword">val</span> in_bits = <span class="type">Input</span>(<span class="type">Vec</span>(<span class="type">InNum</span>, <span class="type">UInt</span>(width.<span class="type">W</span>)))</span><br><span class="line">      <span class="keyword">val</span> out = <span class="type">Output</span>(<span class="type">UInt</span>(width.<span class="type">W</span>))</span><br><span class="line">    &#125;)</span><br><span class="line">    io.out := <span class="type">PriorityMux</span>(io.in_sels, io.in_bits)</span><br><span class="line">&#125;</span><br><span class="line">println(getVerilog(<span class="keyword">new</span> <span class="type">MyPriorityMux</span>(<span class="number">2</span>, <span class="number">32</span>)))</span><br></pre></td></tr></table></figure>
<h2 id="counter">counter</h2>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyCounter</span>(<span class="params">cnt: <span class="type">Int</span>, width: <span class="type">Int</span></span>) <span class="keyword">extends</span> <span class="title">Module</span> </span>&#123;</span><br><span class="line">    <span class="comment">// Example circuit using Mux1H</span></span><br><span class="line">    <span class="keyword">val</span> io = <span class="type">IO</span>(<span class="keyword">new</span> <span class="type">Bundle</span> &#123;</span><br><span class="line">      <span class="keyword">val</span> count = <span class="type">Input</span>(<span class="type">Bool</span>())</span><br><span class="line">      <span class="keyword">val</span> out = <span class="type">Output</span>(<span class="type">UInt</span>(width.<span class="type">W</span>))</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="keyword">val</span> counter = <span class="type">Counter</span>(cnt)  <span class="comment">// 3-count Counter (outputs range [0...2])</span></span><br><span class="line">    when(io.count) &#123;</span><br><span class="line">      counter.inc()</span><br><span class="line">    &#125;</span><br><span class="line">    io.out := counter.value</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">println(getVerilog(<span class="keyword">new</span> <span class="type">MyCounter</span>(<span class="number">3</span>, <span class="number">2</span>))) <span class="comment">// 3-count Counter (outputs range [0...2])</span></span><br></pre></td></tr></table></figure>
<h2 id="map">Map</h2>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">println(<span class="type">List</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>).map(x =&gt; x + <span class="number">1</span>))  <span class="comment">// explicit argument list in function</span></span><br><span class="line">println(<span class="type">List</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>).map(_ + <span class="number">1</span>))  <span class="comment">// equivalent to the above, but implicit arguments</span></span><br><span class="line">println(<span class="type">List</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>).map(_.toString + <span class="string">&quot;a&quot;</span>))  <span class="comment">// the output element type can be different from the input element type</span></span><br><span class="line"></span><br><span class="line">println(<span class="type">List</span>((<span class="number">1</span>, <span class="number">5</span>), (<span class="number">2</span>, <span class="number">6</span>), (<span class="number">3</span>, <span class="number">7</span>), (<span class="number">4</span>, <span class="number">8</span>)).map &#123; <span class="keyword">case</span> (x, y) =&gt; x*y &#125;)  <span class="comment">// this unpacks a tuple, note use of curly braces</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Related: Scala has a syntax for constructing lists of sequential numbers</span></span><br><span class="line">println(<span class="number">0</span> to <span class="number">10</span>)  <span class="comment">// to is inclusive , the end point is part of the result</span></span><br><span class="line">println(<span class="number">0</span> until <span class="number">10</span>)  <span class="comment">// until is exclusive at the end, the end point is not part of the result</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Those largely behave like lists, and can be useful for generating indices:</span></span><br><span class="line"><span class="keyword">val</span> myList = <span class="type">List</span>(<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>, <span class="string">&quot;d&quot;</span>)</span><br><span class="line">println((<span class="number">0</span> until <span class="number">4</span>).map(myList(_)))</span><br></pre></td></tr></table></figure>
<blockquote>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">List</span>(<span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>)</span><br><span class="line"><span class="attribute">List</span>(<span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>)</span><br><span class="line"><span class="attribute">List</span>(<span class="number">1</span>a, <span class="number">2</span>a, <span class="number">3</span>a, <span class="number">4</span>a)</span><br><span class="line"><span class="attribute">List</span>(<span class="number">5</span>, <span class="number">12</span>, <span class="number">21</span>, <span class="number">32</span>)</span><br><span class="line"><span class="attribute">Range</span> <span class="number">0</span> to <span class="number">10</span></span><br><span class="line"><span class="attribute">Range</span> <span class="number">0</span> until <span class="number">10</span></span><br><span class="line"><span class="attribute">Vector</span>(a, b, c, d)</span><br></pre></td></tr></table></figure>
<h2 id="zipwithindex"><strong>zipWithIndex</strong></h2>
</blockquote>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">println(<span class="type">List</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>).zipWithIndex)  <span class="comment">// note indices start at zero</span></span><br><span class="line">println(<span class="type">List</span>(<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>, <span class="string">&quot;d&quot;</span>).zipWithIndex)</span><br><span class="line">println(<span class="type">List</span>((<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>), (<span class="string">&quot;c&quot;</span>, <span class="string">&quot;d&quot;</span>), (<span class="string">&quot;e&quot;</span>, <span class="string">&quot;f&quot;</span>), (<span class="string">&quot;g&quot;</span>, <span class="string">&quot;h&quot;</span>)).zipWithIndex)  <span class="comment">// tuples nest</span></span><br></pre></td></tr></table></figure>
<blockquote>
<figure class="highlight lisp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">List((<span class="number">1</span>,<span class="number">0</span>), (<span class="number">2</span>,<span class="number">1</span>), (<span class="number">3</span>,<span class="number">2</span>), (<span class="number">4</span>,<span class="number">3</span>))</span><br><span class="line">List((<span class="name">a</span>,<span class="number">0</span>), (<span class="name">b</span>,<span class="number">1</span>), (<span class="name">c</span>,<span class="number">2</span>), (<span class="name">d</span>,<span class="number">3</span>))</span><br><span class="line">List(((<span class="name">a</span>,b),<span class="number">0</span>), ((<span class="name">c</span>,d),<span class="number">1</span>), ((<span class="name">e</span>,f),<span class="number">2</span>), ((<span class="name">g</span>,h),<span class="number">3</span>))</span><br></pre></td></tr></table></figure>
<h2 id="reduce"><strong>Reduce</strong></h2>
</blockquote>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">println(<span class="type">List</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>).reduce((a, b) =&gt; a + b))  <span class="comment">// returns the sum of all the elements</span></span><br><span class="line">println(<span class="type">List</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>).reduce(_ * _))  <span class="comment">// returns the product of all the elements</span></span><br><span class="line">println(<span class="type">List</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>).map(_ + <span class="number">1</span>).reduce(_ + _))  <span class="comment">// you can chain reduce onto the result of a map</span></span><br></pre></td></tr></table></figure>
<blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">10</span><br><span class="line">24</span><br><span class="line">14</span><br></pre></td></tr></table></figure>
<h2 id="fold"><strong>Fold</strong></h2>
</blockquote>
<p>类似 <code>reduce</code>，不过可以提供一个初值。</p>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">println(<span class="type">List</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>).fold(<span class="number">0</span>)(_ + _))  <span class="comment">// equivalent to the sum using reduce</span></span><br><span class="line">println(<span class="type">List</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>).fold(<span class="number">1</span>)(_ + _))  <span class="comment">// like above, but accumulation starts at 1</span></span><br><span class="line">println(<span class="type">List</span>().fold(<span class="number">1</span>)(_ + _))  <span class="comment">// unlike reduce, does not fail on an empty input</span></span><br></pre></td></tr></table></figure>
<blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">10</span><br><span class="line">11</span><br><span class="line">1</span><br></pre></td></tr></table></figure>
<h2 id="decoupled-arbiter"><strong>Decoupled Arbiter</strong></h2>
</blockquote>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyRoutingArbiter</span>(<span class="params">numChannels: <span class="type">Int</span></span>) <span class="keyword">extends</span> <span class="title">Module</span> </span>&#123;</span><br><span class="line">  <span class="keyword">val</span> io = <span class="type">IO</span>(<span class="keyword">new</span> <span class="type">Bundle</span> &#123;</span><br><span class="line">    <span class="keyword">val</span> in = <span class="type">Vec</span>(numChannels, <span class="type">Flipped</span>(<span class="type">Decoupled</span>(<span class="type">UInt</span>(<span class="number">8.</span><span class="type">W</span>))))</span><br><span class="line">    <span class="keyword">val</span> out = <span class="type">Decoupled</span>(<span class="type">UInt</span>(<span class="number">8.</span><span class="type">W</span>))</span><br><span class="line">  &#125; )</span><br><span class="line"></span><br><span class="line">  <span class="comment">// YOUR CODE BELOW</span></span><br><span class="line">    io.out.valid := io.in.map(_.valid).reduce(_ || _)</span><br><span class="line">    </span><br><span class="line">  <span class="comment">// 注意，这里是 = 而不是 :=</span></span><br><span class="line">    <span class="keyword">val</span> channel = <span class="type">PriorityMux</span>(</span><br><span class="line">        io.in.map(_.valid).zipWithIndex.map &#123; <span class="keyword">case</span> (valid, index) =&gt; (valid, index.<span class="type">U</span>) &#125;</span><br><span class="line">    )</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">for</span>(i &lt;- <span class="number">0</span> until numChannels) &#123;</span><br><span class="line">        when(channel === i.<span class="type">U</span>) &#123;</span><br><span class="line">            io.in(i).ready := io.out.ready</span><br><span class="line">        &#125;.otherwise&#123;</span><br><span class="line">            io.in(i).ready := <span class="number">0.</span><span class="type">U</span></span><br><span class="line">        &#125;  </span><br><span class="line">    &#125;</span><br><span class="line"><span class="comment">// or    </span></span><br><span class="line"><span class="comment">//     io.in.map(_.ready).zipWithIndex.foreach &#123; case (ready, index) =&gt;</span></span><br><span class="line"><span class="comment">//         ready := io.out.ready &amp;&amp; channel === index.U</span></span><br><span class="line"><span class="comment">//     &#125;</span></span><br><span class="line">    </span><br><span class="line">    io.out.bits := io.in(channel).bits</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="scala-语法">scala 语法</h2>
<h3 id="合并-list">合并 list</h3>
<p>Merge two lists using the <code>++</code>, <code>concat</code>, or <code>:::</code> methods.</p>
<h1 id="functional-programming">Functional Programming</h1>

    </div>

    
    
    

    <div>
      
        <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;">-------The end of this article&nbsp;<i class="fa fa-paw"></i>&nbsp;Thank you for your reading-------</div>
    
</div>
      
    </div>
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>Fitz
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://zhouyuqian.com/2021/05/24/chisel-start/" title="chisel 学习（1）">https://zhouyuqian.com/2021/05/24/chisel-start/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/zh" rel="noopener" target="_blank"><i class="fa fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/FPGA/" <i class="fa fa-tag"></i> FPGA</a>
              <a href="/tags/chisel/" <i class="fa fa-tag"></i> chisel</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2021/05/20/PLL-noise/" rel="prev" title="VCO 噪声优化">
      <i class="fa fa-chevron-left"></i> VCO 噪声优化
    </a></div>
      <div class="post-nav-item">
    <a href="/2021/06/01/docker-vivado/" rel="next" title="在 docker 中安装 vivado">
      在 docker 中安装 vivado <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  

  </div>


          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF-chisel"><span class="nav-number">1.</span> <span class="nav-text">什么是 chisel</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99"><span class="nav-number">2.</span> <span class="nav-text">学习资料</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%AE%89%E8%A3%85"><span class="nav-number">3.</span> <span class="nav-text">安装</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#before-start"><span class="nav-number">4.</span> <span class="nav-text">Before Start</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E8%AF%AD%E6%B3%95"><span class="nav-number">5.</span> <span class="nav-text">语法</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#variables-and-constants---var-and-val"><span class="nav-number">5.1.</span> <span class="nav-text">Variables and Constants - var and val</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#seq"><span class="nav-number">5.2.</span> <span class="nav-text">Seq</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#when"><span class="nav-number">5.3.</span> <span class="nav-text">when</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#for"><span class="nav-number">5.4.</span> <span class="nav-text">for</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#if-or-when"><span class="nav-number">5.5.</span> <span class="nav-text">if or when ?</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8A%A0%E6%B3%95"><span class="nav-number">5.6.</span> <span class="nav-text">加法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%8E%B7%E5%BE%97-verilog-%E4%BB%A3%E7%A0%81"><span class="nav-number">5.7.</span> <span class="nav-text">获得 Verilog 代码</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8F%AF%E8%A7%86%E5%8C%96"><span class="nav-number">5.8.</span> <span class="nav-text">可视化</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%B8%A6%E6%9C%89decoupled%E6%8E%A5%E5%8F%A3%E7%9A%84%E6%A8%A1%E5%9D%97"><span class="nav-number">5.9.</span> <span class="nav-text">带有Decoupled接口的模块</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#queues"><span class="nav-number">5.10.</span> <span class="nav-text">Queues</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#arbiters"><span class="nav-number">5.11.</span> <span class="nav-text">Arbiters</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#popcount"><span class="nav-number">5.12.</span> <span class="nav-text">PopCount</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#reverse"><span class="nav-number">5.13.</span> <span class="nav-text">Reverse</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#onehot-encoding-utilities"><span class="nav-number">5.14.</span> <span class="nav-text">OneHot encoding utilities</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#muxes"><span class="nav-number">5.15.</span> <span class="nav-text">Muxes</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#priority-mux"><span class="nav-number">5.15.1.</span> <span class="nav-text">Priority Mux</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#onehot-mux"><span class="nav-number">5.15.2.</span> <span class="nav-text">OneHot Mux</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#counter"><span class="nav-number">5.16.</span> <span class="nav-text">counter</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#map"><span class="nav-number">5.17.</span> <span class="nav-text">Map</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#zipwithindex"><span class="nav-number">5.18.</span> <span class="nav-text">zipWithIndex</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#reduce"><span class="nav-number">5.19.</span> <span class="nav-text">Reduce</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#fold"><span class="nav-number">5.20.</span> <span class="nav-text">Fold</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#decoupled-arbiter"><span class="nav-number">5.21.</span> <span class="nav-text">Decoupled Arbiter</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#scala-%E8%AF%AD%E6%B3%95"><span class="nav-number">5.22.</span> <span class="nav-text">scala 语法</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%90%88%E5%B9%B6-list"><span class="nav-number">5.22.1.</span> <span class="nav-text">合并 list</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#functional-programming"><span class="nav-number">6.</span> <span class="nav-text">Functional Programming</span></a></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Fitz"
      src="/images/avatar.jpg">
  <p class="site-author-name" itemprop="name">Fitz</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">78</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">25</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">52</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/Starrynightzyq" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;Starrynightzyq" rel="noopener" target="_blank"><i class="fa fa-fw fa-github"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:starrynightzyq@gmail.com" title="E-Mail → mailto:starrynightzyq@gmail.com" rel="noopener" target="_blank"><i class="fa fa-fw fa-envelope"></i>E-Mail</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://space.bilibili.com/57711842" title="Bilibili → https:&#x2F;&#x2F;space.bilibili.com&#x2F;57711842" rel="noopener" target="_blank"><i class="fa fa-fw fa-custom bilibili"></i>Bilibili</a>
      </span>
      <span class="links-of-author-item">
        <a href="http://wpa.qq.com/msgrd?v=3&uin=2421854978&site=qq&menu=yes" title="QQ → http:&#x2F;&#x2F;wpa.qq.com&#x2F;msgrd?v&#x3D;3&amp;uin&#x3D;2421854978&amp;site&#x3D;qq&amp;menu&#x3D;yes" rel="noopener" target="_blank"><i class="fa fa-fw fa-custom qq"></i>QQ</a>
      </span>
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title">
      <i class="fa fa-fw fa-link"></i>
      Links
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="http://leiblog.wang/" title="http:&#x2F;&#x2F;leiblog.wang" rel="noopener" target="_blank">Lei Blog</a>
        </li>
    </ul>
  </div>

      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        
  <div class="beian"><a href="http://beian.miit.gov.cn/" rel="noopener" target="_blank">苏ICP备20042287号 </a>
  </div>

<div class="copyright">
  
  &copy; 2018 – 
  <span itemprop="copyrightYear">2024</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Fitz</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-area-chart"></i>
    </span>
    <span title="站点总字数">251k</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
    <span title="站点阅读时长">3:48</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> 强力驱动 v5.3.0
  </div>
  <span class="post-meta-divider">|</span>
  <div class="theme-info">主题 – <a href="https://mist.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Mist</a> v7.7.2
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="//cdn.jsdelivr.net/gh/theme-next/theme-next-pjax@0/pjax.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js"></script>
  <script src="//cdn.jsdelivr.net/gh/fancyapps/fancybox@3/dist/jquery.fancybox.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/muse.js"></script>


<script src="/js/next-boot.js"></script>

<script src="/js/bookmark.js"></script>

  <script>
var pjax = new Pjax({
  selectors: [
    'head title',
    '#page-configurations',
    '.content-wrap',
    '.post-toc-wrap',
    '#pjax'
  ],
  switches: {
    '.post-toc-wrap': Pjax.switches.innerHTML
  },
  analytics: false,
  cacheBust: false,
  scrollTo : !CONFIG.bookmark.enable
});

window.addEventListener('pjax:success', () => {
  document.querySelectorAll('script[pjax], script#page-configurations, #pjax script').forEach(element => {
    var code = element.text || element.textContent || element.innerHTML || '';
    var parent = element.parentNode;
    parent.removeChild(element);
    var script = document.createElement('script');
    if (element.id) {
      script.id = element.id;
    }
    if (element.className) {
      script.className = element.className;
    }
    if (element.type) {
      script.type = element.type;
    }
    if (element.src) {
      script.src = element.src;
      // Force synchronous loading of peripheral JS.
      script.async = false;
    }
    if (element.getAttribute('pjax') !== null) {
      script.setAttribute('pjax', '');
    }
    if (code !== '') {
      script.appendChild(document.createTextNode(code));
    }
    parent.appendChild(script);
  });
  NexT.boot.refresh();
  // Define Motion Sequence & Bootstrap Motion.
  if (CONFIG.motion.enable) {
    NexT.motion.integrator
      .init()
      .add(NexT.motion.middleWares.subMenu)
      .add(NexT.motion.middleWares.postList)
      .bootstrap();
  }
  NexT.utils.updateSidebarPosition();
});
</script>




  




  
<script src="/js/local-search.js"></script>













    <div id="pjax">
  

  
      

<script>
  if (typeof MathJax === 'undefined') {
    window.MathJax = {
      loader: {
        source: {
          '[tex]/amsCd': '[tex]/amscd',
          '[tex]/AMScd': '[tex]/amscd'
        }
      },
      tex: {
        inlineMath: {'[+]': [['$', '$']]},
        tags: 'ams'
      },
      options: {
        renderActions: {
          findScript: [10, doc => {
            document.querySelectorAll('script[type^="math/tex"]').forEach(node => {
              const display = !!node.type.match(/; *mode=display/);
              const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display);
              const text = document.createTextNode('');
              node.parentNode.replaceChild(text, node);
              math.start = {node: text, delim: '', n: 0};
              math.end = {node: text, delim: '', n: 0};
              doc.math.push(math);
            });
          }, '', false],
          insertedScript: [200, () => {
            document.querySelectorAll('mjx-container').forEach(node => {
              let target = node.parentNode;
              if (target.nodeName.toLowerCase() === 'li') {
                target.parentNode.classList.add('has-jax');
              }
            });
          }, '', false]
        }
      }
    };
    (function () {
      var script = document.createElement('script');
      script.src = '//cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js';
      script.defer = true;
      document.head.appendChild(script);
    })();
  } else {
    MathJax.startup.document.state(0);
    MathJax.texReset();
    MathJax.typeset();
  }
</script>

    

  

    </div>

  <!-- 页面点击小红心 -->
  <!-- <script type="text/javascript" src="/js/jquery-3.3.1.min.js"></script> -->
  <script type="text/javascript" src="/js/clicklove.js"></script><!-- hexo-inject:begin --><!-- hexo-inject:end -->
</body>
</html>
